﻿using System.Collections.Specialized;
using Clipboard.ViewModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SqlSugar;
using Clipboard.Services;
using Microsoft.Extensions.DependencyInjection;
using Clipboard.Model;
using System.IO;
using Clipboard.Model.Enum;
using System.Drawing.Drawing2D;
using CommunityToolkit.Mvvm.Input;
using static Clipboard.Tools.FilePathToNameAndIconConverter;
using static System.Net.Mime.MediaTypeNames;
using System.ComponentModel.DataAnnotations;
using Clipboard.Tools;
using System.Net.NetworkInformation;

namespace Clipboard
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ClipboardViewModel ViewModel { get; }

        //桥梁
        private HwndSource hwndSource;

        // 定义 Windows API 方法
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool AddClipboardFormatListener(IntPtr hwnd);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

        public MainWindow(ClipboardViewModel viewModel)
        {
            // 设置 DataContext 为 ViewModel
            ViewModel = viewModel;
            DataContext = viewModel;

            InitializeComponent();

            //判断是否登录
            RegistryHelper registry = new RegistryHelper();
            string oAuthId = (registry.GetValue("OAuthId") as string) ?? "";
            if (string.IsNullOrEmpty(oAuthId))
                OpenLoginWindowAndCloseThis();
        }


        private void OpenLoginWindowAndCloseThis()
        {
            // 创建登录窗口实例
            LoginViewModel loginViewModel = App.AppHost.Services.GetRequiredService<LoginViewModel>();

            LoginWindow loginWindow = new LoginWindow(loginViewModel, App.AppHost.Services.GetRequiredService<SqlSugarHelper>());

            //// 以模态方式显示登录窗口
            bool? result = loginWindow.ShowDialog();
            if (result!=true)
            {
                System.Windows.Application.Current.Shutdown();  // 退出整个应用
            }
            this.Close();
            return;
        }


        // 最小化
        private void Btn_Min(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }

        // 最大化、还原
        private void Btn_Max(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Normal)
            {
                this.WindowState = WindowState.Maximized;
            }
            else
            {
                this.WindowState = WindowState.Normal;
            }
        }

        // 关闭窗体
        private void Btn_Close(object sender, RoutedEventArgs e)
        {
            this.Hide();  // 隐藏窗口 
            ViewModel.ContextIsShow = true;
            //this.Close();

        }

        // 关闭窗口时移除监听
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            if (hwndSource != null)
            {
                RemoveClipboardFormatListener(hwndSource.Handle);
                hwndSource.RemoveHook(WndProc);
            }
        }

    


        // 窗口初始化后添加钩子
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            IntPtr windowHandle = new WindowInteropHelper(this).Handle;
            hwndSource = HwndSource.FromHwnd(windowHandle);
            if (hwndSource != null)
            {
                hwndSource.AddHook(WndProc);
                AddClipboardFormatListener(windowHandle);
            }
        }

        // 消息处理函数
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            const int WM_CLIPBOARDUPDATE = 0x031D;
            if (msg == WM_CLIPBOARDUPDATE)
            {
                Debug.WriteLine("剪贴板内容发生变化");
                // 这里可以添加更新 UI 或其他逻辑
                handled = true;

                // 使用主线程的 Dispatcher 异步调用 ClipboardAddAsync
                System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
                {
                    try
                    {
                        await ClipoardAddAsync();
                        await ViewModel.LoadClipboardRecords();
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("错误：" + ex.Message);
                    }
                }));


            }

            return IntPtr.Zero;
        }


        // 限制频率
        private static bool canProcess = true;
        private static int aa = 0;
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task ClipoardAddAsync()
        {
            if (!canProcess)
            {
                Debug.WriteLine("aa拦截：");
                return;  // 如果限制频率，跳过
            }
            Debug.WriteLine("aa进入：" + aa++);
            canProcess = false;

            try
            {
                    // 获取 SqlSugar 数据库服务（如果需要保存数据）
                    var sqlSugarHelper = App.AppHost.Services.GetRequiredService<SqlSugarHelper>();
                    var db = sqlSugarHelper.Db;
                // 确保连接已打开
                // 确保连接是打开的

                // 获取剪贴板内容
                if (System.Windows.Clipboard.ContainsText())
                    {
                        string? clipboardText = ClipboardHelper.GetText();
                        if (clipboardText != null)
                        {

                            //判断是否有重复
                            var existingRecord = await db.Queryable<ClipboardRecord>()
                                .Where(record => record.Content == clipboardText)
                                .Where(dataType => dataType.DataType == TypeEnum.Text)
                                .Where(a=>a.UserId==ViewModel.oAuthId)
                                .FirstAsync();

                            if (existingRecord != null && existingRecord.Id > 0)
                            {
                               await db.Updateable<ClipboardRecord>()
                                    .SetColumns(it => new ClipboardRecord()
                                        { Content = clipboardText }) //其实不用更新，我就为了更新时间
                                    .SetColumns(it => new ClipboardRecord() { UpdatedTime = DateTime.Now })
                                    .Where(it => it.Id == existingRecord.Id)
                                    .Where(dataType => dataType.DataType == TypeEnum.Text)
                                    .Where(a => a.UserId == ViewModel.oAuthId)
                                    .ExecuteCommandAsync();
                            }
                            else
                            {
                                // 保存到数据库
                               await db.Insertable(new ClipboardRecord
                                {
                                    Content = clipboardText,
                                    DataType = (int)TypeEnum.Text,
                                    UserId = ViewModel.oAuthId,
                                    CreatedTime = DateTime.Now,
                                    UpdatedTime = DateTime.Now,
                               }).ExecuteCommandAsync();
                            }
                        }
                    }
                    else if (System.Windows.Clipboard.ContainsImage())
                    {
                        // 获取剪贴板中的图片
                        BitmapSource? clipboardImage = ClipboardHelper.GetImage();

                        if (clipboardImage != null)
                        {
                            // 将图片转换为 Base64
                            PngBitmapEncoder encoder = new PngBitmapEncoder();
                            encoder.Frames.Add(BitmapFrame.Create(clipboardImage));

                            using (MemoryStream ms = new MemoryStream())
                            {
                                encoder.Save(ms);
                                byte[] imageBytes = ms.ToArray();
                                string base64Image = Convert.ToBase64String(imageBytes);

                                // 保存到数据库
                                await db.Insertable(new ClipboardRecord
                                {
                                    DataType = TypeEnum.Imges,
                                    UserId = ViewModel.oAuthId,
                                    //Content = base64Image,  // 存储图片为 Base64 图片太大了 不可以
                                    ClipboardFormat = "Image",
                                    CreatedTime = DateTime.Now,
                                    UpdatedTime = DateTime.Now,
                                }).ExecuteCommandAsync();
                            }
                        }

                  

                    }
                    else if (System.Windows.Clipboard.ContainsFileDropList())
                    {
                        // 获取剪贴板中的文件
                        StringCollection? files = ClipboardHelper.GetFiles();

                        if (files != null && files.Count > 0)
                        {
                            StringBuilder hashData = new StringBuilder();
                            List<string> fileList = new List<string>(); //文件  多文件以;连接
                            List<string> fileType = new List<string>(); //文件类型  多文件以;连接

                            foreach (string file in files)
                            {
                                Debug.WriteLine($"文件: {file}");
                                string fileHash = "";
                                long fileInfoLength = 0;
                                string format = "";

                                string type = ""; //文件类型太多不想写枚举了
                                // 获取文件数据和文件信息
                                FileInfo fileInfo = new FileInfo(file);

                                if (fileInfo.Attributes.HasFlag(FileAttributes.Directory))
                                {
                                    // 如果是文件夹
                                    // 将文件夹路径和名称转换为字节数组
                                    byte[] folderPathBytes = Encoding.UTF8.GetBytes(file);
                                    fileHash = GetFileHash(folderPathBytes); // 计算文件路径的哈希值
                                    fileInfoLength = 0;
                                    // 表示是文件夹
                                    format = "Folder";
                                    type = "";
                                }
                                else
                                {
                                    byte[] fileData = File.ReadAllBytes(file);
                                    //fileHash = GetFileHash(fileData);  // 计算文件的哈希值
                                    fileHash = GetFileHash(Encoding.UTF8.GetBytes(file)); // 计算文件路径的哈希值
                                    fileInfoLength = fileInfo.Length;
                                    // 表示是文件
                                    format = "File";
                                    type = fileInfo.Extension;
                                }

                                // 组合哈希值
                                hashData.Append(fileHash);
                                //文件路径
                                fileList.Add(file);
                                //文件类型
                                fileType.Add(type);
                                //文件后缀
                            }

                            // 计算整体哈希
                            string combinedHash = GetFileHash(Encoding.UTF8.GetBytes(hashData.ToString()));

                            string filePaths = string.Join(";", fileList.Cast<string>());

                            string fileSuffix = string.Join(";", fileType.Cast<string>());



                            //判断是否有重复
                            var existingRecord = await db.Queryable<ClipboardRecord>()
                                .Where(record => record.Content == files.Count.ToString())
                                .Where(a => a.UserId == ViewModel.oAuthId)
                                .Where(fileHash => fileHash.FileHash == combinedHash)
                                .Where(dataType => dataType.DataType == TypeEnum.Document)
                                .FirstAsync();


                            if (existingRecord != null && existingRecord.Id > 0)
                            {

                                await db.Updateable<ClipboardRecord>()
                                    .SetColumns(it => new ClipboardRecord()
                                    { Content = files.Count.ToString() }) //其实不用更新，我就为了更新时间
                                    .SetColumns(it => new ClipboardRecord() { UpdatedTime = DateTime.Now })
                                    .Where(it => it.Id == existingRecord.Id)
                                    .Where(a => a.UserId == ViewModel.oAuthId)
                                    .Where(dataType => dataType.DataType == TypeEnum.Document)
                                    .ExecuteCommandAsync();

                            }
                            else
                            {
                                // 保存到数据库 不支持跨设备 地址保存本地
                               await db.Insertable(new ClipboardRecord
                                {
                                    DataType = TypeEnum.Document,
                                    UserId = ViewModel.oAuthId,
                                    Content = files.Count.ToString(), //保存文件个数
                                    FilePath = filePaths, // 存储文件路径
                                    //FileData = fileData,  // 存储文件数据  可以考虑删除 太费数据库了
                                    //FileSize = 0,//不要 多文件不好用。如果要用只能在加一张文件表对应
                                    FileType = fileSuffix, // 存储文件后缀
                                    FileHash = combinedHash,
                                   CreatedTime = DateTime.Now,
                                   UpdatedTime = DateTime.Now,
                                   //ClipboardFormat = format
                               }).ExecuteCommandAsync();
                            }
                        }

                    }
                    else if (System.Windows.Clipboard.ContainsAudio())
                    {
                        // 获取剪贴板中的音频
                    }
                    else
                    {
                        Debug.WriteLine("剪贴板没有[文本,图片,文件,音频]内容");
                    }

                    // 提交事务
                    return;
            }
            catch (Exception ex)
            {
                    Debug.WriteLine("错误："+ex.Message);
            }
            finally
            {
                // 设置为 true，允许下次处理
                await Task.Delay(200);  // 可以调整时间间隔
                canProcess = true;
            }



            //只支持文本，图片，文件 等这些大类


            // 如果重试后仍然失败，给出提示或做出其他处理
            Console.WriteLine("无法打开剪贴板，可能被其他应用程序占用。");
        }


        // 计算文件的 MD5 哈希值
        private string GetFileHash(byte[] fileData)
        {
            using (var md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] hash = md5.ComputeHash(fileData);
                return BitConverter.ToString(hash).Replace("-", "").ToLower();
            }
        }


        ///剪贴板


        /// <summary>
        /// 获取或设置当前正在查看的剪贴板数据。
        /// </summary>
        private IDataObject? _dataObject;

        /// <summary>
        /// 获取剪贴板内容并显示。
        /// </summary>
        private void GetClipboard()
        {
            _dataObject = System.Windows.Clipboard.GetDataObject();
            UpdateObjectTypesUI();
            //CheckCurrentDataObject();
        }

        private void UpdateObjectTypesUI()
        {

        }



        //点击文件
        private void ChangeOver(object sender, MouseButtonEventArgs e)
        {
            // 假设 `sender` 是路径的 TextBox 或其他控件
            string? path = (sender as TextBlock)?.Tag as string; // 或者根据实际情况获取路径

            if (string.IsNullOrEmpty(path))
            {
                MessageBox.Show("路径为空");
                return;
            }

            // 判断路径是否存在
            if (!Directory.Exists(path) && !File.Exists(path))
            {
                MessageBox.Show("路径不存在");
                return;
            }


            try
            {
                // 判断是否是文件夹
                if (Directory.Exists(path))
                {
                    // 打开文件夹
                    Process.Start(new ProcessStartInfo
                    {
                        FileName = path,
                        UseShellExecute = true, // 以文件资源管理器打开
                        Verb = "open" // 执行打开操作
                    });
                }
                else if (File.Exists(path))
                {
                    // 打开文件，使用默认程序
                    Process.Start(new ProcessStartInfo
                    {
                        FileName = path,
                        UseShellExecute = true // 以默认程序打开文件
                    });
                }
            }
            catch (Exception ex)
            {
                // 异常处理：例如文件不存在、权限问题等
                MessageBox.Show($"打开路径时出错：{ex.Message}");
            }



        }


        private int _clickCount = 0;

        private DateTime _lastClickTime;

        //双击事件
        private async void  MouseButtonDownAsync(object sender, MouseButtonEventArgs e)
        {
            // 获取当前时间
            DateTime currentTime = DateTime.Now;

            // 判断双击间隔时间
            if ((currentTime - _lastClickTime).TotalMilliseconds < 500) // 小于 500ms 算作双击
            {
                _clickCount++;
            }
            else
            {
                _clickCount = 1; // 重置点击计数
            }

            _lastClickTime = currentTime;

            // 如果是双击
            if (_clickCount == 2)
            {


                ClipboardRecord? record = (sender as ContentControl)?.Tag as ClipboardRecord; // 或者根据实际情况获取路径


                await Copy(record);

                return;
            }
        }


        /// <summary>
        /// 复制 要使用多线程
        /// </summary>
        /// <param name="record"></param>
        private async Task Copy(ClipboardRecord record)
        {
         
            // 可以在这里安全地更新UI，表示任务即将开始
            try {
                        // 清空剪贴板，确保没有被其他程序占用
                    System.Windows.Application.Current.Dispatcher.Invoke(() =>
                        {
                            try
                            {
                                System.Windows.Clipboard.Clear();
                            }
                            catch (Exception ex)
                            {
                                Debug.WriteLine(Thread.CurrentThread.ManagedThreadId+
                                "：清空剪贴板错误:" + ex.Message);
                            } // 如果失败则忽略错误
                        });

                        switch (record?.DataType)
                        {
                            case TypeEnum.Text:
                                // 复制文本到剪贴板，需要在STA线程中执行
                                System.Windows.Application.Current.Dispatcher.Invoke(() =>
                                {
                                    ClipboardHelper.SetTetx(record?.Content ?? "");
                                });
                                break;
                            case TypeEnum.Imges:
                                // 获取图片
                                //byte[] imageBytes = Convert.FromBase64String(record.Content);
                                //using (MemoryStream ms = new MemoryStream(imageBytes))
                                //{
                                //    BitmapImage bitmapImage = new BitmapImage();
                                //    bitmapImage.BeginInit();
                                //    bitmapImage.StreamSource = ms;
                                //    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                                //    bitmapImage.EndInit();
                                //    // 设置剪贴板图片
                                //    System.Windows.Clipboard.SetImage(bitmapImage);
                                //}
                                break;
                            case TypeEnum.Document:

                                // 获取文件路径
                                string[]? filePaths = record.FilePath?.Split(';');
                                if (filePaths != null && filePaths.Length > 0)
                                {
                                    // 创建 DataObject 并设置文件路径
                                    DataObject dataObject = new DataObject();
                                    StringCollection fileDropList = new StringCollection();
                                    fileDropList.AddRange(filePaths);
                                    // 在STA线程中设置剪贴板文件路径
                                    System.Windows.Application.Current.Dispatcher.Invoke(() =>
                                    {
                                        dataObject.SetFileDropList(fileDropList);
                                        ClipboardHelper.SetFiles(dataObject);
                                      
                                    });
                                }
                                break;
                            case TypeEnum.Sound:
                                // 获取音频
                                //byte[] soundBytes = Convert.FromBase64String(record.Content);
                                //using (MemoryStream ms = new MemoryStream(soundBytes))
                                //{
                                //    SoundPlayer soundPlayer = new SoundPlayer(ms);
                                //    soundPlayer.Play();
                                //}
                                break;
                            default:
                                break;

                        }
            }
            catch (Exception ex)
            {
                // 其他错误
                Debug.WriteLine($"{Thread.CurrentThread.ManagedThreadId}：Exception: {ex.Message}");
                       
            }
         

        }

        private void StyleDown(object sender, RoutedEventArgs e)
        {
            if (sender is Button clickedTextBlock)
            {

                var tag = (KeyValuePair<int, string>?)clickedTextBlock.Tag;


                if (tag.HasValue)
                {
                    _ = ViewModel.OnSortItemClick(tag.Value);
                }
            }
        }


        //托盘事件

        private void TrayIcon_DoubleClick(object sender, EventArgs e)
        {
            // 双击托盘图标时恢复窗口
            this.Show();
            this.WindowState = WindowState.Normal;
        }


        // 重写窗口关闭事件
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            if (e.Cancel == false)
            {
                // 最小化到托盘
                this.Hide();
                e.Cancel = true;
            }
        }
    }
}